﻿/*
   Open Intel 
   Copyright © 2011 – ISC. All Rights Reserved.
*/

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Controls;
using Caliburn.Micro;
using ISC.MapDotNetServer.Common.Data;
using ISC.MapDotNetServer.Common.Maps;
using OI.Events;
using OI.Framework;
using OI.Views;

namespace OI.ViewModels
{
    [Export(typeof(MashupDataViewModel))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class MashupDataViewModel : DataGridScreenViewModelBase, IHandle<QueriedResultSets>
    {
        #region DATA
        readonly IEventAggregator Events;
        public TabControl DatasetTabs { get; private set; }
        public Dictionary<string, QueryResultTable> Datasets = new Dictionary<string, QueryResultTable>();
        public Guid HighlightShapeID;
        public QueriedResultSets LastDisplayedResults { get; set; }
        #endregion

        #region PROPS
        // tabs itemssource
        public BindableCollection<TabItem> Tabs
        {
            get
            {
                if (_Tabs == null)
                {
                    _Tabs = new BindableCollection<TabItem>();
                    _Tabs.CollectionChanged += (s, e) => NotifyOfPropertyChange(() => AreDatasetsAvailable);
                }
                return _Tabs;
            }
            set
            {
                _Tabs = value;
                NotifyOfPropertyChange(() => Tabs);
            }
        }
        private BindableCollection<TabItem> _Tabs;


        // do we have any data to show
        public bool AreDatasetsAvailable
        {
            get
            {
                return Tabs.Count > 0;
            }
        }
        #endregion


        [ImportingConstructor]
        public MashupDataViewModel(IEventAggregator events)
		{
            Events = events;
			events.Subscribe(this);
		}


        // grab the tabs container
        protected override void OnViewLoaded(object view)
        {
            DatasetTabs = ((MashupDataView)view).Tabs;
        }


        // close the selected tab
        public void CloseSelectedTab()
        {
            TabItem selItem = null;
            Tabs.Apply(t => { if (t.IsSelected) selItem = t; });
            if (selItem != null)
            {
                string tableName = selItem.Header.ToString();
                Datasets.Remove(tableName);
                Tabs.Remove(selItem);

                // if there are no more datasets, close panel
                if (Datasets.Count == 0)
                {
                    var p = Parent as MashupViewModel;
                    if (p != null)
                    {
                        p.DataAreaExpanded = false;
                    }
                }
            }
        }


        // handle a query results received event
        public void Handle(QueriedResultSets message)
        {
            // if we are to show the data in this view
            if (message.ShowInDataArea)
            {
                // save last displayed for potential print
                LastDisplayedResults = message;

                // iterate through potentially multiple resultsets (drill-down)
                int idx = 0;
                foreach (var table in message.Tables)
                {
                    // source layer
                    Layer layer = message.Sources != null ? message.Sources[idx++] : null;

                    // the tab header and key into cache
                    string header = ( layer != null ) ?
                                layer.GetLayerName(null) :
                                table.Name;

                    // do we already have this tab open
                    TabItem item = null;
                    if (Datasets.ContainsKey(header))
                    {
                        // just find the tab
                        Tabs.Apply(t => { if (t.Header.ToString() == header) item = t; });
                    }
                    else
                    {
                        // create a new tab
                        item = new TabItem
                        {
                            Header = header,
                            Style = DatasetTabs.Resources["OITabItemStyle"] as Style
                        };
                        Tabs.Add(item);

                        // add dataset to dictionary
                        Datasets.Add(header, table);
                    }

                    // using our active tab item
                    if (item != null)
                    {
                        // if the resultset is empty, remove the tab
                        if (table.QueryResultRows.Count == 0)
                        {
                            Datasets.Remove(header);
                            Tabs.Remove(item);
                        }

                        // select this tab
                        item.IsSelected = true;

                        // update datagrid by dynamically creating a new one
                        var dg = new DataGrid
                        {
                            Style = Application.Current.Resources["OIDataGrids"] as Style
                        };

                        // selecting a row broadcasts a request to zoom to shape
                        dg.SelectionChanged += (s, e) =>
                        {
                            if (e.AddedItems.Count > 0)
                            {
                                var i = e.AddedItems[0];
                                if (i is StringRow)
                                {
                                    var sr = (StringRow)i;

                                    // zoom to feature on datagrid row click
                                    Events.Publish(new ZoomToShape
                                    {
                                        Shape = sr.Shape
                                    });

                                    // clear any previous highlight
                                    Events.Publish(new ClearShape() { ID = HighlightShapeID });

                                    // highlight feature associated with the row
                                    HighlightShapeID = Guid.NewGuid();
                                    Events.Publish(new ShowShape
                                    {
                                        ID = HighlightShapeID,
                                        ShowShapeType = ShowShape.ShowShapeTypes.Highlight,
                                        ShapeSerial = sr.Shape.Serialize()
                                    });
                                }
                            }
                        };

                        // get headings
                        var headings = (layer != null && 
                            layer.MetaData != null &&
                            layer.HasDrilldownHeaders()) ?
                            new List<string>(layer.GetDrilldownHeaders().Split(',')) :
                            table.Fields;

                        // get hyperlink columns
                        var hyperlinkCols = layer.GetHyperlinkColumns();

                        // build a StringTable from the results
                        var st = new StringTable(headings, hyperlinkCols, false);

                        // add rows
                        table.QueryResultRows.ForEach((row) => st.AddRow(row.Values, row.Shape));

                        // bind
                        st.BindStringTableToDataGrid(dg);
                        item.Content = dg;
                    }
                }
            }
        }


        // broadcast request to highlight shapes as you mouseover rows
        public override void GridRowMouseEnter(object item)
        {
            // add custom code here to call when you mouse into of a row
        }
        public override void GridRowMouseLeave(object item)
        {
            // add custom code here to call when you mouse out of a row
        }
    }
}
